﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Mail;
using AutoDownload.Settings;
using Bierdopje.RSS;
using Bierdopje.API;
using TemplateEngine;
using Bierdopje.API.Personal;

namespace AutoDownload.Lib
{
    public class Downloader
    {
        private Config m_ConfigFile;
        private string m_ConfigFileLocation;

        public string ConfigFileLocation
        {
            get { return m_ConfigFileLocation; }
            set { m_ConfigFileLocation = value; }
        }

        public Downloader(string configFile)
        {
            m_ConfigFileLocation = configFile;
            m_ConfigFile = Config.Load(configFile);

            if (m_ConfigFile.APIKey.Equals("0C488FF8DAFDCEF2"))
            {
                m_ConfigFile.APIKey = @"BC4869182255A1C7";
                m_ConfigFile.Save(configFile);
            }
        }

        public Config ConfigFile
        {
            get { return m_ConfigFile; }
        }

        public void Check()
        {
            Sabnzbd.szdConfig _SabnzbdINI = Sabnzbd.SABnzbd.ParseINIFile(ConfigFile.SabnzbdINI);
            ApiLibrary _Api = new ApiLibrary(ConfigFile.APIKey);
            Bierdopje.RSS.BierdopjeFeed _DutchFeed = new BierdopjeFeed(ConfigFile.DutchFeed, _Api);
            Bierdopje.RSS.BierdopjeFeed _EnglishFeed = new BierdopjeFeed(ConfigFile.EnglishFeed, _Api);

            SendOverview(_SabnzbdINI, _Api);

            ConfigFile.Save(ConfigFileLocation);

            DownloadSubs(_SabnzbdINI, _DutchFeed, _EnglishFeed);

            ConfigFile.Save(ConfigFileLocation);
        }

        private void SendOverview(Sabnzbd.szdConfig sabnzbdConfig, ApiLibrary apiLibrary)
        {
            DateTime _CurDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);

            if ((ConfigFile.SendOverview) && (!ConfigFile.PersonalAPIKey.Equals("")) && (_CurDate > ConfigFile.LastOverview) && (sabnzbdConfig.Email.EmailAtEndOfJob))
            {
                ConfigFile.LastOverview = _CurDate;
                ApiPersonal _ApiPersonal = new ApiPersonal(ConfigFile.PersonalAPIKey, apiLibrary);
                Calendar _Cal = _ApiPersonal.getPersonalCalendar();

                //if ((_CurDate.AddDays(-1).Month < DateTime.Now.Month) || (_CurDate.AddDays(-1).Year < DateTime.Now.Year))
                //{ // We zitten in de vorige maand...
                //    if (ConfigFile.PerviousCalendar != null)
                //    {
                //        _Cal = ConfigFile.PerviousCalendar;
                //    }
                //}

                if (_Cal != null)
                {
                    CalendarDay _CalDay = null;
                    foreach (CalendarDay _CD in _Cal.Days)
                    {
                        if (_CD.Date == _CurDate)
                        {
                            _CalDay = _CD;
                            break;
                        }
                    }
                    if (_CalDay != null)
                    {
                        SmtpClient _SC = sabnzbdConfig.Email.getSmtpClient();
                        MailMessage _MM = new MailMessage(new MailAddress(sabnzbdConfig.Email.From), new MailAddress(sabnzbdConfig.Email.To));

                        _MM.Priority = MailPriority.Low;

                        _MM.Subject = ConfigFile.OverviewSubject;
                        string body = "";

                        body += ConfigFile.OverviewHeader;
                        foreach (CalendarEpisode _ep in _CalDay.Episodes)
                        {
                            body += new Engine().Process(ConfigFile.OverviewIterator, _ep);
                        }
                        body += ConfigFile.OverviewFooter;
                        _MM.Body = body;

                        _SC.Send(_MM);
                    }

                    ConfigFile.PerviousCalendar = _Cal;
                }
            }
        }

        private void DownloadSubs(Sabnzbd.szdConfig _SabnzbdINI, Bierdopje.RSS.BierdopjeFeed _DutchFeed, Bierdopje.RSS.BierdopjeFeed _EnglishFeed)
        {
            // Retrieve the feeds from the INI file
            List<Sabnzbd.szdFeed> _FeedsToProcess = new List<Sabnzbd.szdFeed>();
            foreach (string _sabFeedName in ConfigFile.SabnzbdFeeds)
            {
                foreach (Sabnzbd.szdFeed _Feed in _SabnzbdINI.Feeds)
                {
                    if (_Feed.Name.Equals(_sabFeedName))
                    {
                        if (ConfigFile.SpaceToPeriod)
                        {
                            foreach (Sabnzbd.szdFilter _filter in _Feed.Filters)
                            {
                                _filter.SearchString = _filter.SearchString.Replace(' ', '.');
                            }
                        }

                        _FeedsToProcess.Add(_Feed);
                    }
                }
            }

            // Check if there are feeds to process in the INI file
            if (_FeedsToProcess.Count > 0)
            {
                if (ConfigFile.DownloadEnglishSubs)
                {
                    // First fetch the english subs
                    foreach (BierdopjeFeedItem _FeedItem in _EnglishFeed.GetMatchingFeedItems(_FeedsToProcess))
                    {
                        if (!((ConfigFile.IgnoredSubs.Contains(_FeedItem.Link)) || (ConfigFile.DownoadedSubs.Contains(_FeedItem.Link))))
                        {
                            bool download = true;
                            if (ConfigFile.CheckForDutchSubsIfEnglishFound)
                            {
                                if (_FeedItem.ApiAlreadyHasNLSub)
                                {
                                    download = false;
                                }
                            }

                            download = CheckEpisodeAge(_FeedItem, download);

                            if (download)
                            {
                                string TVSortstring = GetTVSortString(_SabnzbdINI, _FeedItem);

                                string Category = _FeedItem.MatchedFilter.Category.ToLower();
                                if (Category.Equals(""))
                                    Category = _FeedsToProcess[0].CategoryName.ToLower();
                                string OutputDir = getOutputDir(_SabnzbdINI, Category);

                                string fileName = Sabnzbd.SABnzbd.CreateSabnzbdFileName(OutputDir,
                                            TVSortstring,
                                            _FeedItem.InfoFromFileName.ShowName,
                                            _FeedItem.InfoFromFileName.Season,
                                            _FeedItem.InfoFromFileName.Episode,
                                            _FeedItem.Title,
                                            _FeedItem.FileNameWithoutVersionInfo);

                               if ((!ConfigFile.DownloadIfNoFilePresent) && (GetEpisodeAge(_FeedItem) >= ConfigFile.DownloadIfNoFilePresentMinAge))
                                {
                                    string fileNameWithoutExtension = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName));

                                    if (!(File.Exists(fileNameWithoutExtension + ".mkv") || File.Exists(fileNameWithoutExtension + ".avi")))
                                    {
                                        download = false;
                                        ConfigFile.IgnoredSubs.Add(_FeedItem.Link);
                                    }
                                }

                               if (download)
                               {
                                   Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                                   HTTPHelper.SaveResponseToFile(_FeedItem.LinkWithDownloadKey, fileName, true);
                                   ConfigFile.DownoadedSubs.Add(_FeedItem.Link);
                                   Notify(_FeedItem, _SabnzbdINI, "ENG", fileName);
                               }
                            }
                            else
                            {
                                ConfigFile.IgnoredSubs.Add(_FeedItem.Link);
                            }
                        }
                    }
                }

                // fetch the dutch subs
                foreach (BierdopjeFeedItem _FeedItem in _DutchFeed.GetMatchingFeedItems(_FeedsToProcess))
                {
                    if (!((ConfigFile.IgnoredSubs.Contains(_FeedItem.Link)) || (ConfigFile.DownoadedSubs.Contains(_FeedItem.Link))))
                    {
                        bool download = CheckEpisodeAge(_FeedItem, true);

                        if (download)
                        {
                            string TVSortstring = GetTVSortString(_SabnzbdINI, _FeedItem);

                            string Category = _FeedItem.MatchedFilter.Category.ToLower();
                            if (Category.Equals(""))
                                Category = _FeedsToProcess[0].CategoryName.ToLower();
                            string OutputDir = getOutputDir(_SabnzbdINI, Category);

                            string fileName = Sabnzbd.SABnzbd.CreateSabnzbdFileName(OutputDir,
                                        TVSortstring,
                                        _FeedItem.InfoFromFileName.ShowName,
                                        _FeedItem.InfoFromFileName.Season,
                                        _FeedItem.InfoFromFileName.Episode,
                                        _FeedItem.Title,
                                        _FeedItem.FileNameWithoutVersionInfo);

                            if ((!ConfigFile.DownloadIfNoFilePresent) && (GetEpisodeAge(_FeedItem) >= ConfigFile.DownloadIfNoFilePresentMinAge))
                            {
                                string fileNameWithoutExtension = Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName));

                                if (!(File.Exists(fileNameWithoutExtension + ".mkv") || File.Exists(fileNameWithoutExtension + ".avi")))
                                {
                                    download = false;
                                    ConfigFile.IgnoredSubs.Add(_FeedItem.Link);
                                }
                            }

                            if (download)
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                                HTTPHelper.SaveResponseToFile(_FeedItem.LinkWithDownloadKey, fileName, true);
                                ConfigFile.DownoadedSubs.Add(_FeedItem.Link);
                                Notify(_FeedItem, _SabnzbdINI, "NL", fileName);
                            }
                        }
                        else
                        {
                            ConfigFile.IgnoredSubs.Add(_FeedItem.Link);
                        }
                    }
                }
            }
        }

        private string GetTVSortString(Sabnzbd.szdConfig sabnzbdINI, BierdopjeFeedItem feedItem)
        {
            string TVSortstring;
            if (sabnzbdINI.EnableTVSorting)
            {
                TVSortstring = sabnzbdINI.TVSortString;
            }
            else
            {
                TVSortstring = "%fn";
            }

            if (ConfigFile.OverWriteRename)
            {
                if (feedItem.ApiEpisode != null) // No inline to force an api read
                {
                    if (feedItem.ApiEpisode.AirDate.AddDays(+1) < ConfigFile.OverWriteRenameUpToDate)
                    {
                        TVSortstring = ConfigFile.OverWriteRenameString;
                    }
                }
            }
            return TVSortstring;
        }

        private bool CheckEpisodeAge(BierdopjeFeedItem _FeedItem, bool download)
        {
            if ((!ConfigFile.DownloadOldSubs) && (download))
            {
                if (GetEpisodeAge(_FeedItem) > ConfigFile.MaxDaysOld)
                {
                    download = false;
                }
            }
            return download;
        }

        private int GetEpisodeAge(BierdopjeFeedItem feedItem)
        {
            ApiEpisode _Episode = feedItem.ApiEpisode;

            if (_Episode != null) // episode not found, must be a bug
            {
                return _Episode.EpisodeAge.Days;
            }
            else
                return 0;
        }

        private void Notify(BierdopjeFeedItem feedItem, Sabnzbd.szdConfig sabConfig, string language, string dest)
        {
            if (sabConfig.Email.EmailAtEndOfJob)
            {
                SmtpClient _SC = sabConfig.Email.getSmtpClient();

                MailMessage _MM = new MailMessage(new MailAddress(sabConfig.Email.From), new MailAddress(sabConfig.Email.To));

                NotifyObject _Notify = new NotifyObject();
                _Notify.Destination = dest;
                _Notify.FeedItem = feedItem;
                _Notify.Language = language;
                _Notify.SabnzbdConfig = sabConfig;

                _MM.Priority = MailPriority.Low;

                _MM.Subject = new Engine().Process(ConfigFile.EmailSubject, _Notify);
                _MM.Body = new Engine().Process(ConfigFile.EmailBody, _Notify);

                _SC.Send(_MM);
            }
        }

        public class NotifyObject
        {
            public BierdopjeFeedItem FeedItem;
            public Sabnzbd.szdConfig SabnzbdConfig;
            public string Language;
            public string Destination;
        }

        private static string getRenamePath(string OutputDir, string TVSortstring)
        {
            string RenamePath;
            if (OutputDir.EndsWith(@"\"))
            {
                RenamePath = OutputDir + TVSortstring;
            }
            else
            {
                RenamePath = OutputDir + @"\" + TVSortstring;
            }
            return RenamePath;
        }

        private static string getOutputDir(Sabnzbd.szdConfig sabnzbdINI, string feedName)
        {

            foreach (Sabnzbd.szdCategory _Category in sabnzbdINI.Categories)
            {
                if (_Category.Name.ToLower().Equals(feedName.ToLower()))
                {
                    if (_Category.Directory.Contains(':'))
                    {
                        return _Category.Directory;
                    }
                    else
                    {
                        return Path.Combine(sabnzbdINI.CompleteDir, _Category.Directory);
                    }
                }
            }
            return sabnzbdINI.CompleteDir;
        }
    }
}
